require 'zip/zip'
require 'zip/zipfilesystem'
require 'iconv'

module Zip
  class ZipFile
    def add_file(file)
      self.add File.basename(file), file
    end
  end
end

class Project < ActiveRecord::Base
  has_many :components

  GROUP_COMPONENTS = [
    { :title => "X月X日福音堂青年聚会", :resource => "cover"},
    { :title => "rules", :resource => "rules"},
    { :title => "欢迎新朋友", :resource => "welcome"},
    { :title => "小组分布图", :resource => "layout"}
  ]

  PRAISE_COMPONENTS = [
    { :title => "X月X日敬拜赞美会", :resource => "praise"},
    { :title => "rules", :resource => "rules"},
    { :title => "欢迎新朋友", :resource => "welcome"}
  ]

  TESTI_COMPONENTS = [
    { :title => "X月X日见证分享会", :resource => "cloud"},
    { :title => "rules", :resource => "rules"},
    { :title => "欢迎新朋友", :resource => "welcome"}
  ]

  BLANK_COMPONENTS = [
    { :title => "新页面" }
  ]

  SUNDAY_COMPONENTS = [
    { :title => "新页面" }
  ]

  MACROS = [
    { :id => :blank, :name => "空白PPT", :components => BLANK_COMPONENTS},
    { :id => :group, :name => "小组聚会", :components => GROUP_COMPONENTS },
    { :id => :praise, :name => "敬拜赞美聚会", :components => PRAISE_COMPONENTS },
    { :id => :testimony, :name => "见证分享聚会", :components => TESTI_COMPONENTS },
    { :id => :sunday, :name => "主日崇拜", :components => SUNDAY_COMPONENTS }
  ]

  def self.new_from_macro(macro_name)
    macro = MACROS.find{ |m| m.id == macro_name }
    return macro || MACROS[0] 
  end

  def js_hash=(hash)
    self.name = hash[:name]
    hash[:components].each_with_index do |c, order|
      com_id = c.delete(:id)
      com = Component.find(com_id) rescue Component.new
      com.js_hash = c
      com.order   = order
      self.components << com
    end
  end

  def jsonize
    {
      :id   => id,
      :name => name,
      :components => components.collect{ |c| c.jsonize }
    }
  end

  def txt
    project_file = "#{project_root}/project.txt"
    project_file_utf8 = "#{project_root}/project.utf8.txt"
    File.open(project_file_utf8, 'w') do |file|
      #file.write "\xEF\xBB\xBF"  # unicode file header
      components.each do |component|
        file.write "#{ w(component.title) }" + LB
        file.write "====#{ w(component.resource) }====" + LB 
        file.write "#{ w(component.body) }" + LB + LB
      end
    end

    `iconv -f utf-8 -t gb18030 #{project_file_utf8} > #{project_file}`
    
    return project_file
  end

  def zip
    zip_file = "#{project_root}/#{self.name}.zip"
    File.delete(zip_file) if File.exists?(zip_file)
    Zip::ZipFile.open(zip_file, Zip::ZipFile::CREATE) do |zip|
      zip.add_file self.txt
      zip.add_file "#{RAILS_ROOT}/public/base.ppt"
      components.collect{ |c| c.resource }.compact.uniq.each do |res|
        zip.add_file "#{template_root}/#{res}.pot"
      end
    end
    File.chmod(0755, zip_file)

    return "#{project_url_root}/#{self.name}.zip"
  end

  private
  LB = "\r\n"

  def w(str)
    #Iconv.iconv('UTF-8', 'gb18030', str)
    str.to_s.strip.gsub("\n", LB)
  end

  def project_url_root
    "/project/#{self.id || 100000}"
  end

  def template_root
    path = "#{RAILS_ROOT}/public/templates"
  end

  def project_root 
    path = "#{RAILS_ROOT}/public" + project_url_root
    FileUtils.mkdir_p(path) unless File.exist?(path)
    path
  end
end
